package com.superzlc.miniweb.servlet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.superzlc.miniweb.servlet.anno.ResponseBody;

public class MainServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		process(request, response);
	}

	// --------------------
	static List<RequestController> requestControllerList = new ArrayList<RequestController>();
	static {
		String rootpath = MainServlet.class.getResource("/").getPath();
		rootpath = new File(rootpath).getPath();
		// 扫描类
		String path = MainServlet.class.getResource("/com/superzlc/miniweb/controller").getPath();
		File file  = new File(path);
		for (File f : file.listFiles()) {
			if (f.isDirectory()) {
				continue;
			}
			if (!f.getPath().endsWith(".class"))
				continue;
			String className = f.getPath().substring(rootpath.length() + 1);
			StringBuffer sb = new StringBuffer(className);
			for (int i = 0; i < className.length(); i++) {
				if (className.charAt(i) == File.separatorChar)
					sb.setCharAt(i, '.');
			}
			className = sb.toString();
			className = className.substring(0, className.length() - ".class".length());
			try {
				System.out.println("[info] 扫描到类：" + className);
				Class<?> clazz = Class.forName(className);
				regist(clazz);
			} catch (ClassNotFoundException e) {
			}
		}
	}

	static void regist(Class<?> clazz) {
		System.out.println("[info] 注册Controller - " + clazz.getName());
		// 获取类和基本路径
		RequestController rc = new RequestController(clazz);
		if (rc.init()) {
			requestControllerList.add(rc);
			return;
		}
	}

	protected RequestAction getRequestAction(String actionPath) {
		// 循环匹配每个，直到匹配到
		RequestAction ra;
		for (RequestController rc : requestControllerList) {
			ra = rc.getRequestAction(actionPath);
			if (ra != null) {
				return ra;
			}
		}
		return null;
	}

	protected void process(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		System.out.println("[info] 处理请求 - " + request.getRequestURL());
		// 获取路径
		// String actionPath = request.getPathInfo();
		String actionPath = request.getPathInfo();
		if (actionPath == null) {
			actionPath = request.getServletPath();
		} else {
			actionPath = request.getServletPath() + actionPath;
		}
		if ((actionPath == null) || (actionPath.equals(""))) {
			actionPath = "/";
		}

		// 获取处理方法
		System.out.println("[info] 匹配路径 - " + actionPath);
		RequestAction ra = getRequestAction(actionPath);
		if (ra == null) {
			Error404(request, response);
			return;
		}
		System.out.println("[info] 匹配到 - " + ra);
		// 调用处理方法
		Object ret;
		try {
			ret = ra.invoke(request, response);
		} catch (Exception e) {
			e.printStackTrace();
			Error505(request, response, e);
			return;
		}

		// 1.空对象，要做的已经在action中做了
		if (ret == null)
			return;
		// 2.对非字符串对象应该特殊处理，比如转为json或下载文件之类
		ResponseBody rb = ra.method.getAnnotation(ResponseBody.class);
		if (rb != null) {
			if (ret instanceof String) {
				response.getWriter().write((String)ret);
			}
			return;
		}

		String path = (String)ret;
		if (path == null || path.length() == 0) {
			return;
		}
		// 3.重定向
		if (path.toLowerCase().startsWith("redirect:")) {
			path = path.substring(0, "redirect:".length()).trim();
			System.out.println("[info] 请求重定向 " + path);
			response.sendRedirect(path);
			return;
		} else if (path.toLowerCase().startsWith("forward:")) {
			// 4.转发
			path = path.substring(0, "forward:".length()).trim();
			System.out.println("[info] 请求转发 " + path);
			RequestDispatcher rd = request.getRequestDispatcher(path);
			rd.forward(request, response);
			return;
		}
		// 5.调用视图
		path = "/WEB-INF/" + path + ".jsp";
		Model model = ra.getModel();
		if (model != null) {
			model.addAttribute2Request(request);
		}
		System.out.println("[info] 调用视图 " + path);
		RequestDispatcher rd = request.getRequestDispatcher(path);
		rd.forward(request, response);
		return;
	}

	protected void Error404(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.sendError(404, "Page No Find");
		return;
	}

	protected void Error505(HttpServletRequest request,
			HttpServletResponse response, Exception e) throws ServletException, IOException {
		response.sendError(505, e.getMessage());
		return;
	}
}
